#################################### 函数库
import numpy as np
import adi
import pyModeS as pms
from timeit import default_timer as timer
from numba import jit
import queue, time
import sys

from rich.live import Live
from rich.table import Table

from rich.console import Console
console = Console()
#################################### 常数
FS = 4e6
n = int(FS/2e6)
N = 10*n
M = 240*n
A = 2*n
B = 7*n
C = 9*n
#################################### 配置pluto
# 连接硬件
try:
    sdr = adi.Pluto("ip:192.168.2.1")
except:
    print('pluto无法连接')
    exit()
else:
    print('pluto连接成功')
# 采样率
sdr.sample_rate = int(FS)
# 增益模式
sdr.gain_control_mode = "slow_attack"
# 接收带宽
sdr.rx_rf_bandwidth = int(4e6)
# 接收中心频率
sdr.rx_lo = int(1090e6)
# 接收数据输出类型
sdr.rx_output_type = 'double'
# 接收数据块长度
sdr.rx_buffer_size = 400000


##################################### 预处理
cache = queue.Queue(maxsize=1000)
data = sdr.rx()
LEN = len(data)-M

loc = np.arange(16*n,M,2*n)

TH = np.sum(np.abs(data))/len(data)*6
print('当前门限：', TH)
#################################### 函数
@jit(nopython=True)
def FindPreamble(data):
    preamble = []
    i = 0
    while i<LEN:
        if data[i] & data[i+A] & data[i+B] & data[i+C]:
            preamble.append(i)
            i += M
        else:
            i += 1
    return preamble


@jit(nopython=True)
def ADSdemod(preamble, data):
    msg = []
    for k in preamble:
        target = data[k:k+M]
        mes = []
        for i in loc:
            if target[i] & (not target[i+2]):
                mes.append('1')
            elif (not target[i]) & target[i+2]:
                mes.append('0')
            else:
                break
        if len(mes)>110:
            msg.append(mes)
    return msg


def ADSdecode(msg):
    msg = ''.join(msg)
    msg = str(hex(int(msg,2)))[2:]
    if pms.df(msg) == 17:
        t = pms.typecode(msg)
        ic = pms.icao(msg)
        if (t>=9 and t<=18) or (t>=20 and t<=22):           
            pos = pms.adsb.position_with_ref(msg, 28.22, 112.99)
            alt = pms.adsb.altitude(msg)
            WriteMssage(ic, 0, pos, alt)
        elif t == 19:
            v = pms.adsb.velocity(msg)
            WriteMssage(ic, 1, v)   
    return 'ok'


icao = ['test']
upTime = 30 # 30秒无新数据删除
# 信息格式：0-纬度，1-经度，2-高度，3-水平速度，4-角度，5-垂直速度，6-显示时间
adsMess = np.zeros((7,1))
def WriteMssage(ic, num, arg1, arg2=0):
    global adsMess, icao, upTime
    if num == 0:
        if ic in icao:
            where = np.argwhere(icao==ic)[0][0]
            adsMess[0:2,where] = np.array([arg1[1], arg1[0]])
            adsMess[2,where] = arg2*0.3048 # 英尺转米
            adsMess[6,where] = upTime # 刷新
        else:
            icao = np.append(icao,ic)
            arr = np.append(np.array([arg1[1], arg1[0]]), np.array([arg2*0.3048, 0, 0, 0, upTime]))
            adsMess = np.c_[adsMess,np.reshape(np.array(arr),(7,1))]
    else:
        if ic in icao:
            where = np.argwhere(icao==ic)[0][0]
            # vA: (159, 182.88, -832, ’GS’) 一节=1.582km/h
            adsMess[3,where] = arg1[0]*1.852
            adsMess[4,where] = arg1[1]
            adsMess[5,where] = arg1[2]*1.852
            adsMess[6,where] = upTime # 刷新  
    return 0


#################################### 处理数据
def Process():
    global adsMess, icao

    if cache.empty():
        pass
    else:
        #tic = timer()
        # 读取数据
        data = cache.get()
        # 门限对比
        data = np.greater(data, TH)
        # 导前检测
        pre = FindPreamble(data)
        try:
            # 信号解调
            if len(pre)>1:
                msg = ADSdemod(pre, data)
                for i in msg:
                    ADSdecode(i)
        except:
            print('error')
            pass
                
        #toc = timer()
        #print('处理耗时：', toc - tic, '秒') # 输出的时间，秒为单位
    return 'ok'



#################################### 读取数据
def ReadRx():
    #tic = timer()
    data = np.abs(sdr.rx())
    cache.put(data)
    #toc = timer()
    #print('读取耗时：', toc - tic, '秒') # 输出的时间，秒为单位
    return 1


#################################### 显示数据
def TransMess():
    global adsMess, icao
    dic = [{
        'type': "Feature",
        'geometry': 
            {
            'type': "Point",
            'coordinates': [112.99, 28.22],
            },
        'properties': 
            {
            'ICAO': "00000",
            'height':"0m",
            'speed':"0m/s",
            'angle':"0",
            'vspeed':"0m/s"
            
            },
        }]
    if len(icao)>1:
        for i in range(1, len(icao)):
            dic.append(CreateDict(adsMess[0][i], adsMess[1][i], icao[i], adsMess[2][i], adsMess[3][i], adsMess[4][i], adsMess[5][i]))
    return dic

def CreateDict(lon, lat, ICAO, height, speed, angle, vspeed):
    dic = {
        "type":"Feature",
        "geometry":
        {
            'type': "Point",
            'coordinates': [lon, lat],
        },
        'properties':
        {
            'ICAO': ICAO,
            'height':str(np.int(height))+'m',
            'speed':str(np.int(speed))+'m/s',
            'angle':str(np.int(angle))+'度',
            'vspeed':str(np.int(vspeed))+'m/s',
            
        },
    }

    return dic
